﻿using System;
using System.Collections.Generic;
using Microsoft.SharePoint;
using System.Web.UI;
using System.Xml.Linq;

namespace Eneta.Portal.Common
{
    public static class SPExtensions
    {
        //public static SPListItem _GetProfile(this SPUser user)
        //{
        //    string queryString = "<Where><Eq><FieldRef Name=\"SysID\" /><Value Type=\"Text\">{0}</Value></Eq></Where>";
        //    var userName = user.ToString();
        //    if (userName.Contains("liveid:"))
        //        queryString = string.Format(queryString, user.ToString().Substring(7));
        //    else
        //        queryString = string.Format(queryString, user.ToString());
        //    SPQuery query = new SPQuery();
        //    query.Query = queryString;

        //    SPListItemCollection items = SPContext.Current.Site.RootWeb.Lists["ProfileList"].GetItems(query);
        //    if (items.Count == 0)
        //        return null;
        //    return items[0];
        //}

        public static Control FindControl(this Control control, string name, bool recursive)
        {
            if (!recursive)
                return control.FindControl(name);

            foreach (Control child in control.Controls)
            {
                if (child.ID == name)
                    return child;
                var ctl = child.FindControl(name, recursive);
                if (ctl != null)
                    return ctl;
            }
            return null;
        }

        //public static bool _GetBool(this SPListItem item, string field, bool defaultValue)
        //{
        //    try
        //    {
        //        var value = item[item.Fields.GetFieldByInternalName(field).Id];
        //        if (value == null)
        //            return defaultValue;

        //        bool result = defaultValue;
        //        bool.TryParse(value.ToString(), out result);
        //        return result;
        //    }
        //    catch(ArgumentOutOfRangeException aex)
        //    {
        //        Logger.LogWarning("GetBool(): cannot find field " + field, "SPExtensions");
        //        Logger.LogException(aex);
        //        throw;
        //    }
        //}

        //public static bool _HasWeb(SPWebCollection webs, string webTitle, out SPWeb web)
        //{
        //    foreach (SPWeb currentWeb in webs)
        //    {
        //        if (currentWeb.Title == webTitle)
        //        {
        //            web = currentWeb;
        //            return true;
        //        }
        //    }
        //    web = null;
        //    return false;
        //}

        public static bool HasWeb(this SPWeb web, string webName, out string webId)
        {
            foreach (SPWeb currentWeb in web.Webs)
            {
                if (currentWeb.Title == webName)
                {
                    webId = currentWeb.ID.ToString();
                    return true;
                }
            }
            webId = string.Empty;
            return false;
        }
        
        public static bool HasList(this SPWeb web, string listName)
        {
            foreach(SPList list in web.Lists)
                if (list.Title == listName)
                    return true;
            return false;
        }

        public static bool HasField(this SPList list, string fieldName)
        {
            foreach (SPField field in list.Fields)
            {
                if (field.InternalName == fieldName)
                {
                    return true;
                }
            }
            return false;
        }

        public static void AddFieldsToContentType(this SPWeb web, string listName, string contentTypeName)
        {
            if (web == null)
                return;
            var list = web.Lists[listName];
            if (list == null)
                return;
            var cType = list.ContentTypes[contentTypeName];
            if (cType == null)
                return;
            foreach (var link in list.GetFieldLinks())
            {
                if (!cType.Fields.ContainsField(link.Name))
                    cType.FieldLinks.Add(link);
            }
            cType.Update();
        }

        public static List<SPFieldLink> GetFieldLinks(this SPList list)
        {
            var fields = new List<SPFieldLink>();
            foreach (SPField field in list.Fields)
            {
                if (!field.Hidden && !field.ReadOnlyField)
                {
                    fields.Add(new SPFieldLink(field));
                }
            }
            return fields; 
        }

        /// <summary>
        /// This is incase of site columns. There is no target list.
        /// </summary>
        /// <param name="web"></param>
        /// <param name="sourceListName"></param>
        /// <param name="fieldInternalName"></param>
        public static void EnsureLookupField(this SPWeb web, string sourceListName, string fieldInternalName)
        {
            if (web == null)
                return;
            if (!web.Fields.ContainsField(fieldInternalName))
                return;
            SPFieldLookup field = web.Fields.GetFieldByInternalName(fieldInternalName) as SPFieldLookup;
            
            if (field == null)
                return;
            
            if (!web.HasList(sourceListName))
                return;

            Console.WriteLine("Before LookupField {0} SchemaXML: {1}", fieldInternalName, field.SchemaXml);
            XElement fieldSchemaXml = XElement.Parse(field.SchemaXml);
            //Deleting the invalid field and adding new one. Cannot change the list or update schema - field is invalid still.
            if (!field.CanBeDeleted)
                return;
            if (field.CanBeDeleted)
            {
                field.Delete();
            }

            var listAttribute = fieldSchemaXml.Attribute(XName.Get("List"));
            listAttribute.Value = web.Lists[sourceListName].ID.ToString("B");

            web.Fields.AddFieldAsXml(fieldSchemaXml.ToString());

            field = web.Fields.GetFieldByInternalName(fieldInternalName) as SPFieldLookup;

            field.LookupWebId = web.ID;
            field.AllowMultipleValues = true;
            field.Update();

            Console.WriteLine("After LookupField {0} SchemaXML: {1}", fieldInternalName, field.SchemaXml);
        }

        public static void EnsureLookupField(this SPWeb web, string targetListName, string sourceListName, string fieldInternalName)
        {
            if (web == null)
                return;
            if (!web.HasList(targetListName))
                return;
            SPList list = web.Lists[targetListName];
            if (!list.HasField(fieldInternalName))
                return;
            SPFieldLookup field = list.Fields.GetFieldByInternalName(fieldInternalName) as SPFieldLookup;
            if (field == null)
                return;
            if (!web.HasList(sourceListName))
                return;
            field.LookupList = web.Lists[sourceListName].ID.ToString();
            field.Update();
        }

        public static void AddFieldToContentType(this SPWeb web, string fieldInternalName, string contentTypeName)
        {
            var contentType = web.ContentTypes[contentTypeName] as SPContentType;
            if (contentType == null)
                return;
            var field = web.Fields.GetField(fieldInternalName) as SPField;
            if (field == null)
                return;

            if (!contentType.Fields.ContainsField(field.InternalName))
            {
                contentType.FieldLinks.Add(new SPFieldLink(field));
                contentType.Update();
            }
        }

        public static bool IsSet(this object o)
        {
            if (o == null)
                return false;
            return true;
        } 
    }
}
